﻿using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;

namespace Communication.Help.Crc;

public static class Crc16Xmodem
{
    private const ushort Init = 0x0000;
    private static readonly ushort[] Table = Crc16Utils.GenerateTable(0x1021, false);

    public static ushort Compute(ReadOnlySpan<byte> data)
    {
        var crc = Init;
        foreach (var b in data)
            crc = (ushort)((crc << 8) ^ Table[((crc >> 8) ^ b) & 0xFF]);
        return crc;
    }

    public static ushort Compute(ReadOnlySequence<byte> data)
    {
        var crc = Init;

        foreach (var b in data)
        {
            foreach (var c in b.Span)
            {
                crc = (ushort)((crc << 8) ^ Table[((crc >> 8) ^ c) & 0xFF]);
            }
        }

        return crc;
    }

    public static ushort Compute(IEnumerable<byte> data)
    {
        return data.Aggregate(Init,
            static (current, b) => (ushort)((current << 8) ^ Table[((current >> 8) ^ b) & 0xFF]));
    }
}